home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Source Code / C / Applications / Python 1.3.3 / Python 133 68K / Mac / Lib / socket.py < prev    next >
Text File  |  1996-05-20  |  6KB  |  305 lines

  1. """socket.py for mac - Emulate socket module with mactcp and macdnr
  2.  
  3. Currently only implements TCP sockets (AF_INET, SOCK_STREAM).
  4. Esoteric things like socket options don't work,
  5. but getpeername() and makefile() do work; everything used by ftplib works!
  6. """
  7.  
  8. # Jack Jansen, CWI, November 1994 (initial version)
  9. # Guido van Rossum, CWI, March 1995 (bug fixes and lay-out)
  10.  
  11.  
  12. import mactcp
  13. import MACTCPconst
  14. import macdnr
  15.  
  16.  
  17. # Exported constants
  18.  
  19. _myerror = 'socket_wrapper.error'
  20. error = (mactcp.error, macdnr.error, _myerror)
  21.  
  22. SOCK_DGRAM = 1
  23. SOCK_STREAM = 2
  24.  
  25. AF_INET = 1
  26.  
  27.  
  28. # Internal constants
  29.  
  30. _BUFSIZE = 15*1024            # Size of TCP/UDP input buffer
  31.  
  32. _myaddress = None
  33. _myname = None
  34. _myaddrstr = None
  35.  
  36.  
  37. def _myipaddress():
  38.     global _myaddress
  39.     if _myaddress == None:
  40.         _myaddress = mactcp.IPAddr()
  41.     return _myaddress
  42.  
  43.  
  44. def _ipaddress(str):
  45.     if type(str) == type(1):
  46.         return str            # Already numeric
  47.     ptr = macdnr.StrToAddr(str)
  48.     ptr.wait()
  49.     return ptr.ip0
  50.  
  51.  
  52. def gethostbyname(str):
  53.     id = _ipaddress(str)
  54.     return macdnr.AddrToStr(id)
  55.  
  56.  
  57. def gethostbyaddr(str):
  58.     id = _ipaddress(str)
  59.     ptr = macdnr.AddrToName(id)
  60.     ptr.wait()
  61.     name = ptr.cname
  62.     if name[-1:] == '.': name = name[:-1]
  63.     names, addresses = [], [str]
  64.     return name, names, addresses
  65.  
  66. def gethostname():
  67.     global _myname
  68.     if _myname == None:
  69.         id = _myipaddress()
  70.         ptr = macdnr.AddrToName(id)
  71.         ptr.wait()
  72.         _myname = ptr.cname
  73.     return _myname
  74.  
  75.  
  76. def _gethostaddress():
  77.     global _myaddrstr
  78.     if _myaddrstr == None:
  79.         id = _myipaddress()
  80.         _myaddrstr = macdnr.AddrToStr(id)
  81.     return _myaddrstr
  82.  
  83.  
  84. def socket(family, type, *which):
  85.     if family <> AF_INET:
  86.         raise _myerror, 'Protocol family %d not supported' % type
  87.     if type == SOCK_DGRAM:
  88.         return _udpsocket()
  89.     elif type == SOCK_STREAM:
  90.         return _tcpsocket()
  91.     raise _myerror, 'Protocol type %d not supported' % type
  92.  
  93.  
  94. def fromfd(*args):
  95.     raise _myerror, 'Operation not supported on a mac'
  96.  
  97.  
  98. class _socket:
  99.     def unsupported(self, *args):
  100.         raise _myerror, 'Operation not supported on this socket'
  101.     
  102.     accept = unsupported
  103.     bind = unsupported
  104.     close = unsupported
  105.     connect = unsupported
  106.     fileno = unsupported
  107.     getpeername = unsupported
  108.     getsockname = unsupported
  109.     getsockopt = unsupported
  110.     listen = unsupported
  111.     recv = unsupported
  112.     recvfrom = unsupported
  113.     send = unsupported
  114.     sendto = unsupported
  115.     setblocking = unsupported
  116.     setsockopt = unsupported
  117.     shutdown = unsupported
  118.  
  119.  
  120. class _tcpsocket(_socket):
  121.     
  122.     def __init__(self):
  123.         self.stream = mactcp.TCPCreate(_BUFSIZE)
  124.         ##self.stream.asr = self.asr
  125.         self.databuf = ''
  126.         self.udatabuf = ''
  127.         self.port = 0
  128.         self.accepted = 0
  129.         self.listening = 0
  130.  
  131.     def accept(self):
  132.         if not self.listening:
  133.             raise _myerror, 'Not listening'
  134.         self.listening = 0
  135.         self.stream.wait()
  136.         self.accepted = 1
  137.         return self, self.getsockname()
  138.     
  139.     # bind has two ways of calling: s.bind(host, port) or s.bind((host, port));
  140.     # the latter is more proper but the former more common
  141.     def bind(self, a1, a2=None):
  142.         if a2 is None:
  143.             host, port = a1
  144.         else:
  145.             host, port = a1, a2
  146.         self.port = port
  147.         
  148.     def close(self):
  149.         if self.accepted:
  150.             self.accepted = 0
  151.             return
  152.         self.stream.Abort()
  153.     
  154.     # connect has the same problem as bind (see above)
  155.     def connect(self, a1, a2=None):
  156.         if a2 is None:
  157.             host, port = a1
  158.         else:
  159.             host, port = a1, a2
  160.         self.stream.ActiveOpen(self.port, _ipaddress(host), port)
  161.         
  162.     def getsockname(self):
  163.         host, port = self.stream.GetSockName()
  164.         host = macdnr.AddrToStr(host)
  165.         return host, port
  166.         
  167.     def getpeername(self):
  168.         st = self.stream.Status()
  169.         host = macdnr.AddrToStr(st.remoteHost)
  170.         return host, st.remotePort        
  171.         
  172.     def listen(self, backlog):
  173.         self.stream.PassiveOpen(self.port)
  174.         self.listening = 1
  175.         
  176.     def makefile(self, rw = 'r', bs = 512):
  177.         return _socketfile(self, rw, bs)
  178.         
  179.     def recv(self, bufsize, flags=0):
  180.         if flags:
  181.             raise _myerror, 'recv flags not yet supported on mac'
  182.         if not self.databuf:
  183.             try:
  184.                 self.databuf, urg, mark = self.stream.Rcv(0)
  185.             except mactcp.error, arg:
  186.                 if arg[0] != MACTCPconst.connectionClosing:
  187.                     raise mactcp.error, arg
  188.         rv = self.databuf[:bufsize]
  189.         self.databuf = self.databuf[bufsize:]
  190.         return rv
  191.         
  192.     def send(self, buf):
  193.         self.stream.Send(buf)
  194.         return len(buf)
  195.         
  196.     def shutdown(self, how):
  197.         if how == 0:
  198.             return
  199.         self.stream.Close()
  200.         
  201.     def bytes_readable(self):
  202.         st = self.stream.Status()
  203.         return st.amtUnreadData
  204.         
  205.     def bytes_writeable(self):
  206.         st = self.stream.Status()
  207.         return st.sendWindow - st.sendUnacked;
  208.  
  209.  
  210. class _udpsocket(_socket):
  211.     
  212.     def __init__(self):
  213.         pass
  214.  
  215.  
  216. class _socketfile:
  217.     
  218.     def __init__(self, sock, rw, bs):
  219.         if rw[1:] == 'b': rw = rw[:1]
  220.         if rw not in ('r', 'w'): raise _myerror, "mode must be 'r' or 'w'"
  221.         self.sock = sock
  222.         self.rw = rw
  223.         self.bs = bs
  224.         self.buf = ''
  225.         
  226.     def read(self, length = -1):
  227.         if length < 0:
  228.             length = 0x7fffffff
  229.         while len(self.buf) < length:
  230.             new = self.sock.recv(0x7fffffff)
  231.             if not new:
  232.                 break
  233.             self.buf = self.buf + new
  234.         rv = self.buf[:length]
  235.         self.buf = self.buf[length:]
  236.         return rv
  237.         
  238.     def readline(self):
  239.         import string
  240.         while not '\n' in self.buf:
  241.             new = self.sock.recv(0x7fffffff)
  242.             if not new:
  243.                 break
  244.             self.buf = self.buf + new
  245.         if not '\n' in self.buf:
  246.             rv = self.buf
  247.             self.buf = ''
  248.         else:
  249.             i = string.index(self.buf, '\n')
  250.             rv = self.buf[:i+1]
  251.             self.buf = self.buf[i+1:]
  252.         return rv
  253.         
  254.     def readlines(self):
  255.         list = []
  256.         line = self.readline()
  257.         while line:
  258.             list.append(line)
  259.             line = self.readline()
  260.         return list
  261.         
  262.     def write(self, buf):
  263.         BS = self.bs
  264.         if len(buf) >= BS:
  265.             self.flush()
  266.             self.sock.send(buf)
  267.         elif len(buf) + len(self.buf) >= BS:
  268.             self.flush()
  269.             self.buf = buf
  270.         else:
  271.             self.buf = self.buf + buf
  272.     
  273.     def writelines(self, list):
  274.         for line in list:
  275.             self.write(line)
  276.     
  277.     def flush(self):
  278.         if self.buf and self.rw == 'w':
  279.             self.sock.send(self.buf)
  280.             self.buf = ''
  281.     
  282.     def close(self):
  283.         self.flush()
  284.         ##self.sock.close()
  285.         del self.sock
  286.  
  287.  
  288. def __test_tcp():
  289.     s = socket(AF_INET, SOCK_STREAM)
  290.     s.connect('poseidon.cwi.nl', 13)
  291.     rv = s.recv(1000)
  292.     print 'Time/date:', rv
  293.     rv = s.recv(1000)
  294.     if rv:
  295.         print 'Unexpected extra data:', rv
  296.     s.close()
  297.     
  298.  
  299. def __test_udp():
  300.     s = socket(AF_INET, SOCK_DGRAM)
  301.     print 'Sending data... (hello world)'
  302.     s.sendto(('poseidon.cwi.nl', 7), 'hello world')
  303.     rv, host = s.recvfrom(1000)
  304.     print 'Got from ', host, ':', rv
  305.